package epam.car.rent.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import dataAccess.DbWriter;
import epam.car.rent.Car;
import epam.car.rent.Client;
import epam.car.rent.Management;
import epam.car.rent.Manager;
import epam.car.rent.Order;
import epam.car.rent.OrderState;
import epam.car.rent.exceptions.ClientException;

enum Actions{
	APPROVEORDER,
	LOGIN,
	REQUESTCLIENTS,
	REGISTER,
	RENTCAR, 
	LOGOUT,
	SETLANG
}

public class Controller extends javax.servlet.http.HttpServlet {
	
	static Logger log = Logger.getLogger("carrentlogger");
	
	public static HttpSession session = null;
	static PrintWriter w = null;
	@Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    @Override
    public void destroy() {
        super.destroy();
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	session = req.getSession(true);
        
    	req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");
        
        w = resp.getWriter();
        w.write("<html><body>");

        String act = prepareURI(req);
        
        w.write("<strong>Token action: " + act + "</strong><br />");
      switch (Actions.valueOf(act)) {
		case LOGIN:
			if(login(req)!=null){
				w.write("Logged in.");	
			}else{
				w.write("<div style=\"color:#ff0000;\">Incorrect password!</div>");
			}
			resp.sendRedirect(getServletContext().getContextPath()+"/index.jsp");
//			w.write("<script>window.location.href=\""+getServletContext().getContextPath()+"index.jsp\"</script>");
			break;
		case REGISTER:
			w.write("trying to register... <br />");
			
			if(register(req)!=null){
				w.write("Registered: "+(String)session.getAttribute("clientID"));	
			}else{
				w.write("<div style=\"color:#ff0000;\">Error!</div>");
			}
			resp.sendRedirect(getServletContext().getContextPath()+"/index.jsp");
//			w.write("<script>window.location.href=\""+getServletContext().getContextPath()+"index.jsp\"</script>");
			break;
		case LOGOUT:
			w.write("trying to logout... <br />");
			logout();
			resp.sendRedirect(getServletContext().getContextPath()+"/index.jsp");
//			w.write("<script>window.location.href=\""+getServletContext().getContextPath()+"index.jsp\"</script>");
			break;
		case RENTCAR:
			rentCar(req);
			resp.sendRedirect(getServletContext().getContextPath()+"/index.jsp");
//			w.write("<script>window.location.href=\""+getServletContext().getContextPath()+"index.jsp\"</script>");
			break;
		case SETLANG:
			w.write("setting the language...<br />");
			
			setLanguage(req);
			resp.sendRedirect(getServletContext().getContextPath()+"/index.jsp");

//			w.write("<script>window.location.href=\""
//					+ getServletContext().getContextPath()
//					+ "index.jsp\"</script>");
			break;
		case REQUESTCLIENTS:
			w.write("trying to print clients...<br />");
			requestAllClients(req);
			break;
		case APPROVEORDER:
			ApproveOrder(req);
			resp.sendRedirect(getServletContext().getContextPath()+"/index.jsp");
//			w.write("<script>window.location.href=\""+getServletContext().getContextPath()+"index.jsp\"</script>");
			break;
		default:
			break;
		}
        w.write("</body></html>");
    }
    @Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

    }
    
    private String prepareURI(HttpServletRequest URI){
    	return URI.getRequestURI().toString().replace("/", "").toUpperCase();
    }
    
    private Order rentCar(HttpServletRequest req) {
    	if (req.getParameter("clientId").equals("null")){
    		w.write("You must be logged in for renting a car!<br />");
    	} else{
    		w.write("Trying to rent a car<br />");
        	w.write("Car id: "+ req.getParameter("carId")+", client: "+req.getParameter("clientId"));
        	Calendar cal = new GregorianCalendar();
        	w.write(new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()));
        	Car c = DbWriter.getCarById(Long.valueOf(req.getParameter("carId")));
        	
        	Order o = Management.rentCar(DbWriter.getManagerById("admin"), 
    				c, 
    				DbWriter.getClientById((String) session.getAttribute("clientID")), 
    				new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()));
        	w.write("Order created: "+o.toString());
        	DbWriter.update(c);
        	DbWriter.addToDb(o);
    		return o;
    	}
		return null;
    }
    
    private String login(HttpServletRequest req) {
    	String login = req.getParameter("login");
    	String password = req.getParameter("password");
    	if (login.matches("[\\p{L}]{2}[0-9]{6}")){
    		Client client = null;
    		try {
    			client = DbWriter.getClientById(login);
    			if (client.getPassword().equals(password)){
    				session.setAttribute("clientID", client.getPassportId());
    				log.info("Client with pid="+client.getPassportId()+" is logged in");
    				return client.getPassportId();
    			}
    		} catch (NullPointerException e) {
    			log.warn("Login problem: no such client");
    			return "No Such Client!";
    		}
    	}else { // i'm assuming that admin is trying to login
    		Manager manager = null;
    		try{
    			manager = DbWriter.getManagerById(login);
    			if(manager.getPassword().equals(password)){
    				session.setAttribute("adminID", manager.getName());
    				log.info("Administrator with name="+manager.getName()+" is logged in");
    				return manager.getName();
    			}
    		}catch (NullPointerException e){
    			log.warn("Login problem: no such administrator");
    			return "No such manager!";
    		}
    	}
		return null;
    }
    
    private void logout() {
    	if (session.getAttribute("clientID")!=null){
    		log.info("Client with pid="+session.getAttribute("clientID")+" is logged out");
    		session.setAttribute("clientID", null);	
    	}else if (session.getAttribute("adminID")!=null){
    		log.info("Administrator with name="+session.getAttribute("adminID")+" is logged out");
    		session.setAttribute("adminID", null);
    	}
    }
    
    private String register(HttpServletRequest req) {
    	w.write("Trying to create a client...");
    	try {
			Client c = new Client(req.getParameter("name"), req.getParameter("pid"),
					Float.valueOf(req.getParameter("money")),req.getParameter("password"), 
					req.getParameter("email"));
			DbWriter.addToDb(c);
			log.info("New user registered, pid="+c.getPassportId());
			session.setAttribute("clientID", c.getPassportId());
			log.info("User with pid="+c.getPassportId()+" is logged in");
    		return c.getPassportId();
		} catch (NumberFormatException e) {
			log.warn("Number format exception till registering new user ("+e.getMessage()+")");
		} catch (ClientException e) {
			log.warn("Exception till registering new user: "+e.getMessage());
		}
		return null;
    }
    
    private void requestAllClients(HttpServletRequest req){
    	if (session.getAttribute("adminID")!=null){
	    	//DbWriter.requestAllFromDb();
			ArrayList<Client> clients = DbWriter.getAllClients();
			w.write("<table border=1 cellspacing='5' cellpadding='5'>");
			w.write("<tr><td>Name</td><td>Passport ID</td><td>Money</td><td>Email</td></tr>");
			for (Client c : clients) {
				w.write("<tr><td>"+c.getName()+"</td><td>"
						+c.getPassportId()+"</td>"
						+"<td>"+c.getMoney()+"</td>"
						+"<td>"+c.getEmail()+"</td>"
						+"<td>"+c.getPassword()+"</td>"
								+"</tr>");
			}
			w.write("</table>");
	        w.write("</body></html>");
	        log.info("Administrator with name="+session.getAttribute("adminID")+" requested a list of all clients");
		} else{
			w.write("You must have administrator privileges to see this list");
			if (session.getAttribute("clientID")!=null){
				log.warn("User with pid="+session.getAttribute("clientID")
						+" tried to see the list of clients");	
			}else {
				log.warn("Anonymous tried to see the list of clients");	
			}
		}
    }
    
    private void setLanguage(HttpServletRequest req){
		
    	String lang = req.getParameter("lang");
    	Locale locale = null;

		if (lang.equals("Russian")) {
			locale = new Locale("ru", "RU");
//			w.write("russian<br/>");
		} else if (lang.equals("Ukrainian")) {
			locale = new Locale("ua", "UA");
//			w.write("ukrainian<br/>");
		} else if (lang.equals("English")) {
			locale = new Locale("en", "EN");
//			w.write("english<br/>");
		}
//		w.write(locale.toString()+"<br />");
		
		session.setAttribute("myLocale", locale);
		
		ResourceBundle bundle = ResourceBundle.getBundle("/i18n/crBundle", locale);

		for (Enumeration e = bundle.getKeys(); e.hasMoreElements();) {
			String key = (String) e.nextElement();
			String s = bundle.getString(key);
			session.setAttribute(key, s);
		}
		
		log.info("UI language changed");
    }
    
    private void ApproveOrder(HttpServletRequest req){
    	Order o = DbWriter.getOrderById(Long.valueOf(req.getParameter("orderId")));
    	
    	if (session.getAttribute("adminID")!=null){
    		
    		w.write(o.toString());
    		
    		o.setState(OrderState.APPROVED);
    		
    		DbWriter.update(o);
    		
    		w.write(DbWriter.getOrderById(o.getId()).toString());
    		
	        log.info("Administrator with name="+session.getAttribute("adminID")+" just approved an order with id="+o.getId());
		} else{
			w.write("You must have administrator privileges to see this list");
			if (session.getAttribute("clientID")!=null){
				log.warn("User with pid="+session.getAttribute("clientID")
						+" tried to see the list of clients");	
			}else {
				log.warn("Anonymous tried to approve an order");	
			}
		}
    }
}
